#include <Precomp.h>
#include <defs.h>
#include <winsock.h>
#include <packet.h>
#include <serverconnection.h>

CServerConnection::CServerConnection() { }

void CServerConnection::SendLoginRequest(const char* szName, const char* szPass, const char* szLogin, bool isQuery)
{
  struct login_cpacket packet;

  strcpy_s(packet.name, sizeof(packet.name), szName);
  strcpy_s(packet.password, sizeof(packet.password), szPass);

  strcpy_s(packet.login, sizeof(packet.login), szLogin);

  packet.type = (char) EClientPacketType_Login;
  packet.query = isQuery ? 1 : 0;
  SendPacket((packet_base *) &packet);
}

void CServerConnection::SendTeamRequest(ETeamID eTeamID, int iShip)
{
    struct outfit_cpacket outfitReq;

    outfitReq.type = (EClientPacketType) EClientPacketType_OutfitToNewShip;
    outfitReq.team = (char) eTeamID;
    outfitReq.ship = (char) iShip;

    SendPacket((packet_base *) &outfitReq);
}

void CServerConnection::SendPickSocket()
{
    int     newPort;
    struct socket_cpacket sockPack;
    
    newPort = (6000 & 32767);
    while (newPort < 2048 || newPort == ntohs(GetPort()))
    {
      newPort = (newPort + 10687) & 32767;
    }

    sockPack.type = (BYTE) EClientPacketType_Socket;
    sockPack.socket = htonl(newPort);
    sockPack.version = (char) SOCKVERSION;
    sockPack.udp_version = (char) UDPVERSION;
    SendPacket((packet_base *) &sockPack);
}

void CServerConnection::SendPacket(packet_base* pPacket)
{
    int iLen = CPacket::GetClientPacketLen((EClientPacketType) (pPacket->type));

    CPacket::ToNetworkByteOrder(pPacket);

    WriteData((BYTE *)pPacket, iLen);
}


void CServerConnection::UpdateWithPacketSink(IPacketSink* pPacketSink)
{
    Update();

    ProcessReadBuffer(pPacketSink);
}


void CServerConnection::ProcessReadBuffer(IPacketSink* pPacketSink)
{
    int cbCur = 0;
    int cbLeft = GetCBBufferedRead();
    const BYTE* pbReadBuffer = GetReadBufferHead();

    for(;;) // While(true)
    {
        if(cbLeft == 0)
        {
            break;
        }

        EServerPacketType packetType = (EServerPacketType) pbReadBuffer[cbCur];

        int cbLen = CPacket::GetServerPacketLen(packetType);

        if(cbLeft < cbLen)
        {
            break;
        }

        int cbOld = cbCur;

        cbCur += cbLen;
        cbLeft -= cbLen;

        if(!ProcessPacket(pPacketSink, packetType, (packet_base*) (pbReadBuffer + cbOld)))
        {
            break;
        }
    }

    ConsumeReadBuffer(cbCur);
}


bool CServerConnection::ProcessPacket(IPacketSink* pPacketSink, EServerPacketType ePacketType, packet_base* pPacket)
{
    CPacket::FromNetworkByteOrder(pPacket);

    return pPacketSink->ProcessPacket(ePacketType, pPacket);   
}

